home *** CD-ROM | disk | FTP | other *** search
Text File | 1991-05-01 | 19.8 KB | 690 lines | [TEXT/MPS ] |
- //UMacAppUniversal.cp
- //Copyright © 1984-1991 Apple Computer, Inc. All rights reserved.
-
- #include "UMacAppUniversal.h"
-
- #ifndef __GEOMETRY__
- #include <Geometry.h>
- #endif
-
- #ifndef __TRAPS__
- #include <Traps.h>
- #endif
-
- #ifndef __SYSEQU__
- #include <SysEqu.h>
- #endif
-
- #ifndef __DEVICES__
- #include <Devices.h>
- #endif
-
- #ifndef __ULOMEM__
- #include <ULoMem.h>
- #endif
-
- #ifndef __MEMORY__
- #include <Memory.h>
- #endif
-
- #ifndef __TOOLUTILS__
- #include <ToolUtils.h>
- #endif
-
- #ifndef __RESOURCES__
- #include <Resources.h>
- #endif
-
- #ifndef __FONTS__
- #include <Fonts.h>
- #endif
-
- #ifndef __SCRAP__
- #include <Scrap.h>
- #endif
-
- #ifndef __ERRORS__
- #include <Errors.h>
- #endif
-
- #ifndef __DIALOGS__
- #include <Dialogs.h>
- #endif
-
- #ifndef __PACKAGES__
- #include <Packages.h>
- #endif
-
- #ifndef __SCRIPT__
- #include <Script.h>
- #endif
-
- #ifndef __OSEVENTS__
- #include <OSEvents.h>
- #endif
-
- #ifndef __SANE__
- #include <SANE.h>
- #endif
-
- #ifndef __GESTALTEQU__
- #include <GestaltEqu.h>
- #endif
-
- #ifndef __EDITIONS__
- #include <Editions.h>
- #endif
-
- #ifndef __QUICKDRAW__
- #include <QuickDraw.h>
- #endif
-
- #ifndef __MENUS__
- #include <Menus.h>
- #endif
-
- #ifndef __UDebug__
- #include "UDebug.h"
- #endif
-
- #ifndef __UERRORMGR__
- #include "UErrorMgr.h"
- #endif
-
- #ifndef __UMEMORY__
- #include "UMemory.h"
- #endif
-
- #ifndef __UMACAPPUTILITIES__
- #include "UMacAppUtilities.h"
- #endif
-
- //--------------------------------------------------------------------------------------------------
- // Nothing in this module can be allowed to fail!
- #pragma $MC68020-
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAUtilitiesRes
-
- pascal void BlockSet(Ptr destPtr,
- long byteCount,
- SignedByte setVal)
- // Much thanks for this improved version to Scott D. Schmitz
-
- {
- Ptr endPtr = NULL;
- long longSetVal = 0;
- LongIntPtr longEndPtr = NULL;
- LongIntPtr longSetValPtr;
-
- destPtr = (Ptr)StripLong(destPtr);
- endPtr = (Ptr)(destPtr + byteCount);
- longEndPtr = (LongIntPtr)(destPtr + (byteCount & 0xFFFFFFFC));//Trunc to nearest 4 bytes
-
- //We do longword assignments when we have a chance
- if (byteCount >= 4)
- {
- if ((((long)destPtr) & 1) == 1) //Starting on an odd byte boundry
- *destPtr++ = setVal;
-
- longSetVal = (setVal << 12) + (setVal << 8) + (setVal << 4) + setVal;// Lets get a 4 byte 'punch'.
-
- //Assign in 4 byte chunks what we can
- for (longSetValPtr = (LongIntPtr)destPtr; longSetValPtr < longEndPtr;)
- *longSetValPtr++ = longSetVal;
- destPtr = (Ptr)longSetValPtr;
- }
-
- //Now finish assigning odd bytes
- while (destPtr < endPtr)
- *destPtr++ = setVal;
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAUtilitiesRes
- // This must always be in a resident segment as aRect may be within a handle
-
- pascal void CenterRectOnScreen(Rect& aRect,
- Boolean horizontally,
- Boolean vertically,
- Boolean forDialog)
-
- {
- Point screenSize(qd.screenBits.bounds.Length(vSel) - GetMBarHeight(), qd.screenBits.bounds.Length(hSel));
- Point rectSize(aRect.Length(vSel), aRect.Length(hSel));
- short newSize = 0;
-
- // Calculate screen size minus menu bar
- if (horizontally)
- aRect.left = (screenSize.h - rectSize.h) / 2;
- if (vertically)
- if (forDialog)
- {
- newSize = (screenSize.v - rectSize.v) / 5;
- aRect.top = (short)(Max(newSize, 10) + GetMBarHeight());
- }
- else
- aRect.top = (screenSize.v - rectSize.v) / 2;
-
- aRect.right = aRect.left + rectSize.h;
- aRect.bottom = aRect.top + rectSize.v;
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAUtilitiesRes
-
- pascal void ConcatNumber(const Str255& aString,
- long aNumber,
- Str255& theResult)
-
- {
- NumToString(aNumber, theResult);
- theResult = aString + theResult;
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAUtilitiesRes
-
- pascal TrapType GetTrapType(short theTrap)
-
- {
- // OS traps start with A0, Tool with A8 or AA.
- if ((theTrap & 0x0800) == 0) // per D.A.
- return OSTrap;
- else
- return ToolTrap;
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAMiniInit
-
- pascal void DoRealInitToolBox(void)
-
- {
- InitGraf(&qd.thePort);
- InitFonts();
- InitWindows(); // creates non-relocatable for the WM port
-
- // _DON'T_ flush disk-inserted or os events or you'll be sorry!
- FlushEvents(everyEvent - diskMask - osMask, 0);
-
- InitMenus();
- TEInit();
- InitDialogs(NULL);
- CursHandle aCursHandle = GetCursor(watchCursor); /* Watch should be in system file, but just
- in case… */
-
- InitCursor(); /* !!! This forces an arrow cursor. Is there
- a way to reset the show/hide level and
- init all the cursor goo without having
- this visual glitch? ( the Finder™ sets the
- cursor to a watch when launching. It would
- be nice to stay that way until the app is
- ready for events. */
- if (aCursHandle)
- SetCursor(**aCursHandle); // Change cursor to watch
-
- /* -1 == 0xFFFFFFFF, the largest 32 bit address. Our routine StripLong uses a pre-stripped
- address gStrippedAddress to avoid the yucky MPW glue.
- (NOTE: need gStrippedAddress in DefineConfiguration.) */
- gStrippedAddress = StripAddress((Ptr) - 1);
-
- // Find out just what kind of environment we're dealing with here
- DefineConfiguration(gConfiguration);
-
- // Init all the primary colors
- SetRGBColor(gRGBBlack, 0, 0, 0);
- SetRGBColor(gRGBWhite, 0xFFFF, 0xFFFF, 0xFFFF);
- SetRGBColor(gRGBRed, 0xFFFF, 0, 0);
- SetRGBColor(gRGBGreen, 0, 0xFFFF, 0);
- SetRGBColor(gRGBBlue, 0, 0, 0xFFFF);
-
- #if qDebug || qInspector
- gFieldToStrRtn = (ProcPtr) & StdFieldToString;
- gFieldToCountRtn = (ProcPtr) & StdFieldToCount;
- #endif
-
- gBoolString[0][0] = (char)5; // = "\pFALSE";
- gBoolString[0][1] = 'F';
- gBoolString[0][2] = 'A';
- gBoolString[0][3] = 'L';
- gBoolString[0][4] = 'S';
- gBoolString[0][5] = 'E';
- gBoolString[1][0] = (char)4; // = "\pTRUE";
- gBoolString[1][1] = 'T';
- gBoolString[1][2] = 'R';
- gBoolString[1][3] = 'U';
- gBoolString[1][4] = 'E';
-
- // The refnum where the application's resources should be found
- gApplicationRefNum = CurResFile();
-
- gToolBoxInitialized = TRUE;
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment Main
- // This procedure is intended to be in "Main" which is already loaded
-
- extern pascal void _DataInit(void); // Routine in the A5 globals initializer
-
- pascal void FailedInitToolBox(void)
-
- {
- if (qDebug)
- DebugStr("Not enough room to init ToolBox Managers");
- ExitToShell(); /*??? any good way to signal this to the user
- ???*/
- }
-
- pascal void InitToolBox(void)
-
- {
- const short kBreathingRoom = 1024; // Amount of heap space needed for init
- Size totalSize = 0;
- Size contigSize = 0;
- Handle h = NULL;
-
- /* the heap and stack don't overlap. So there's enough room to init the managers.
- Make sure that the MAMiniInit Segment can be loaded and that there's still a little
- Room after that. */
-
- UnloadSeg(&_DataInit); // Toss some ballast
-
- /* "MAMain" this is MacApp's own code that must be resident… even before/during the UMemory startup.
- GetNamedResource will call RsrvMem which locates the handle as low in memory as possible.
- We will then lock it there… just like "Main". In order for this to work correctly the build system
- will have to have set the locked bit on the MAMain resource. */
- h = GetNamedResource('CODE', "MAMain");
- if (h)
- HNoPurge(h);
- else
- FailedInitToolBox();
-
- h = GetNamedResource('CODE', "MAMiniInit");
- if (h)
- HNoPurge(h); /* don't let it get squished out of the heap when the grow zone might get called
- below. However, since it is not locked it will float up to the top of the heap
- when it is entered at DoRealInitToolBox. */
-
- else
- FailedInitToolBox();
-
- /* Attempt to ensure that there is going to be kBreathingRoom bytes available in the heap so that
- when the actual toolbox managers are initialized there is a significantly reduced chance that
- they will express their displeasure with us through SysErr -25 or -2. If the space is not
- currently available in the zone as shown by PurgeSpace then attempting to allocate it will let
- growzoneproc operate and grow the zone a little, as necessary. If, after that, we haven't been
- able to get the breathing room we desire then just give up and fade silently away. (Like the old
- soldier, not the old executive). */
-
- PurgeSpace(totalSize, contigSize);
-
- if (totalSize >= kBreathingRoom)
- DoRealInitToolBox();
- else
- {
- h = NewHandle(kBreathingRoom);
- if (h != NULL) // get the grow space
- {
- DisposHandle(h);
- DoRealInitToolBox();
- }
- else
- FailedInitToolBox(); // Give up
- }
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAMiniInit
-
- pascal Boolean ValidateConfiguration(const ConfigRecord& configuration)
-
- {
- Boolean isSupported = TRUE;
-
- /* Run the gauntlet of support tests using the conditionally set constants.
- If any single test fails then the app is considered unsupported on this machine. */
-
- // Required minimums
- isSupported = isSupported && configuration.hasROM128K;
- isSupported = isSupported && configuration.hasScriptManager;
- isSupported = isSupported && configuration.hasHierarchicalMenus;
- isSupported = isSupported && configuration.hasStyleTextEdit;
- isSupported = isSupported && configuration.hasWaitNextEvent;
-
- // Optionally required
- if (qNeedsColorQD)
- isSupported = isSupported && configuration.hasColorQD;
-
- if (qNeedsMC68020)
- isSupported = isSupported && ((configuration.processor != gestalt68000) && (configuration.processor != gestalt68010));
-
- if (qNeedsMC68030)
- isSupported = isSupported && ((configuration.processor != gestalt68000) && (configuration.processor != gestalt68010) && (configuration.processor != gestalt68020));
-
- if (qNeedsFPU)
- isSupported = isSupported && configuration.hasFPU;
-
- // System 7.0 Support
-
- if (qNeedsAppleEventMgr)
- isSupported = isSupported && configuration.hasAppleEventMgr;
-
- if (qNeedsEditionMgr)
- isSupported = isSupported && configuration.hasEditionMgr;
-
- if (qNeedsHelpMgr)
- isSupported = isSupported && configuration.hasHelpMgr;
-
- if (qNeedsAliasMgr)
- isSupported = isSupported && configuration.hasAliasMgr;
-
- if (qNeedsFolderMgr)
- isSupported = isSupported && configuration.hasFolderMgr;
-
- if (qNeedsProcessMgr)
- isSupported = isSupported && configuration.hasProcessMgr;
-
- return isSupported;
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAMiniInit
-
- pascal short GetSysMap(void) = { /* kMoveWAbsolute */
- 0x3EB8, /* SysMap */ 0xA58};/* retrieve global; reference number of
- system map */
- // MOVE.W SysMap,(SP)
-
- short GetSysVRefNum(void)
- // return the working directory refNum corresponding to the currently open System File
-
- {
- FCBPBRec aFCBPBRec;
- HParamBlockRec aHParamBlockRec;
- WDPBRec aWDPBRec;
-
- // get file info for open system file rsrc fork
- BlockSet((Ptr) & aFCBPBRec, sizeof(FCBPBRec), 0x00);
- aFCBPBRec.ioRefNum = GetSysMap();
- if (PBGetFCBInfoSync(&aFCBPBRec) != noErr)
- return 0;
- else
- {
- // get volume info for open system file rsrc fork
- BlockSet((Ptr) & aHParamBlockRec, sizeof(HParamBlockRec), 0x00);
- aHParamBlockRec.volumeParam.ioVRefNum = aFCBPBRec.ioFCBVRefNum;
- if (PBHGetVInfoSync(&aHParamBlockRec) != noErr)
- return 0;
- else
- {
- // open a working directory for system file and return a reference to it
- BlockSet((Ptr) & aWDPBRec, sizeof(WDPBRec), 0x00);
- aWDPBRec.ioVRefNum = aHParamBlockRec.volumeParam.ioVRefNum;
- aWDPBRec.ioWDDirID = aHParamBlockRec.volumeParam.ioVFndrInfo[0];
- aWDPBRec.ioWDProcID = 'ERIK'; //0x4552494B; //'ERIK'
- if (PBOpenWDSync(&aWDPBRec) != noErr)
- return 0;
- else
- return aWDPBRec.ioVRefNum;
- }
- }
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAMiniInit
-
- Boolean HasGestaltAttr(OSType itsAttr,
- short itsBit)
-
- {
- long response;
-
- return (Gestalt(itsAttr, response) == noErr) && (((response >> itsBit) & 1) != 0);
- }
-
-
- pascal void DefineConfiguration(ConfigRecord& configuration)
-
- {
- const short mDesktopBus = 0x0400;
-
- OSErr err;
- long response;
-
- err = Gestalt(gestaltVersion, response);
- configuration.environsVersion = (short)response;
-
- err = Gestalt(gestaltMachineType, response);
- configuration.machineType = (short)response;
-
- configuration.hasROM128K = configuration.machineType >= gestaltMac512KE;
- if (configuration.hasROM128K)
- configuration.hasHFS = TRUE;
- else
- configuration.hasHFS = GetFSFCBLen() > 0;
-
- err = Gestalt(gestaltSystemVersion, response);
- configuration.systemVersion = (short)response;
-
- err = Gestalt(gestaltProcessorType, response);
- configuration.processor = (short)response;
-
- err = Gestalt(gestaltFPUType, response);
- configuration.hasFPU = response != gestaltNoFPU;
-
- err = Gestalt(gestaltQuickdrawVersion, response);
- configuration.hasColorQD = response != gestaltOriginalQD;
-
- err = Gestalt(gestaltQuickdrawVersion, response);
- configuration.has32BitQD = configuration.hasColorQD && (response != gestalt8BitQD);
-
- err = Gestalt(gestaltKeyboardType, response);
- configuration.keyboardType = (short)response;
-
- err = Gestalt(gestaltMachineType, response);
- configuration.atDrvrVersNum = (short)response;
-
- configuration.hasSCSI = HasGestaltAttr(gestaltHardwareAttr, gestaltHasSCSI);
-
- err = Gestalt(gestaltAUXVersion, response);
- configuration.hasAUX = response != 0;
-
- err = Gestalt(gestaltScriptMgrVersion, response);
- configuration.hasScriptManager = configuration.hasROM128K && (response != 0);
-
- configuration.hasTempMem = HasGestaltAttr(gestaltOSAttr, gestaltTempMemSupport);
-
- //!!! still need to set Atversion
-
- configuration.sysVRefNum = GetSysVRefNum();
-
- err = Gestalt(gestaltTextEditVersion, response);
- configuration.teVersion = response;
-
- configuration.hasDesktopBus = (GetHwCfgFlags() & mDesktopBus) > 0;
-
- configuration.hasHierarchicalMenus = configuration.hasROM128K && TrapExists(_PopUpMenuSelect);
-
- configuration.hasStyleTextEdit = configuration.systemVersion >= 0x600;
- configuration.hasSoundManager = configuration.hasROM128K && TrapExists(_SndDoCommand);
- configuration.hasWaitNextEvent = configuration.hasROM128K && TrapExists(_WaitNextEvent);
-
- // System 7.0 support
- configuration.hasAppleEventMgr = HasGestaltAttr(gestaltAppleEventsAttr, gestaltAppleEventsPresent);
- configuration.hasEditionMgr = HasGestaltAttr(gestaltEditionMgrAttr, gestaltEditionMgrPresent);
- configuration.hasHelpMgr = HasGestaltAttr(gestaltHelpMgrAttr, gestaltHelpMgrPresent);
- configuration.hasAliasMgr = HasGestaltAttr(gestaltAliasMgrAttr, gestaltAliasMgrPresent);
- configuration.hasFolderMgr = HasGestaltAttr(gestaltFindFolderAttr, gestaltFindFolderPresent);
- configuration.hasPopupCDEF = HasGestaltAttr(gestaltPopupAttr, gestaltPopupPresent);
-
- if (configuration.systemVersion >= 0x700) // why isn't there a Gestalt selector ???
- configuration.hasProcessMgr = TRUE;
- else
- configuration.hasProcessMgr = FALSE;
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment Main
- pascal void HdlInitFailed(short error,
- long message,
- void* )
-
- {
- //!!! would be nice to unloadallsegments here if (the memory unit is inited
- if (error != noErr) /* check to see if an alert has already been
- displayed */
- {
- if (message == 0)
- message = msgInitFailed; // if no message specified, use our own
-
- #if qDebug
- // UnloadSeg(&PLFlush); ¿¿¿ what's the equivalent for C++ ???
- #endif
-
- ErrorAlert(error, message);
-
- ExitToShell();
- }
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment Main
- // Essential one-time initialization
-
- void ClearTheFPU(void) = { 0x42A7, 0x42A7, 0xF21F, 0x9800 };
- // INLINE 0x42A7, // CLR.L -(A7)
- // 0x42A7, // CLR.L -(A7)
- // 0xF21F, 0x9800; // FMOVEM (A7)+, FPCR/FPSR
-
- pascal void InitUMacApp(short callsToMoreMasters)
- // Must be in the Main segment since all other segments get unloaded from here.
-
- {
- short initSeg;
- THz applZone;
- short oldMoreMast;
-
- if (!gToolBoxInitialized)
- InitToolBox();
-
- if (ValidateConfiguration(gConfiguration)) /* Make sure we can run. The programmer
- really should have ensured this in their
- "M" file but this is a backup check just
- in case. After all 68000's don't really
- like to RTD.*/
- {
- /* the main procedure is always compiled with universal code so, the FPU must be reset before it
- is used. We could get spurious crashes or worse.
- Remember: 2+2=4… every time!
- */
- if (qNeedsFPU || gConfiguration.hasFPU)
- ClearTheFPU();
-
- // Init the basics used by the ErrorMgr
- gMacAppAlertFilter = (ProcPtr) & MacAppAlertFilter;
- gInFilter = FALSE;
- gInhibitNestedHandling = FALSE; // Allow nested handling
-
- // Install the permanent Outermost failure handler
- long junk;
- CatchFailures(pFi, &HdlInitFailed, &junk);
-
- // Install MacApp's Memory management system
- InitUMemory();
-
- UnloadAllSegments();
-
- // Here is a trick suggested by Jerome C.--it allocates one large block of master pointers
- applZone = ApplicZone();
- oldMoreMast = applZone->moreMast;
- applZone->moreMast = oldMoreMast * callsToMoreMasters;
- MoreMasters();
- applZone->moreMast = oldMoreMast;
-
- LoadResidentSegments();
-
- // Force the init segment to be memory resident, so we can call UnloadAllSegs during init
- initSeg = GetSegNumber((ProcPtr) & DoInitUMacApp);
- SetResidentSegment(initSeg, TRUE);
-
- DoInitUMacApp(); // do rest of initialization
-
- SetResidentSegment(initSeg, FALSE); // make it non-resident
- UnloadAllSegments();
- }
- else
- {
- StdAlert(phUnsupportedConfiguration);
- ExitToShell(); // leave the application pronto!
- }
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment Main
- // Must be in main segment as it is called in early initialization && in MacAppAlert
-
- pascal void PullApplicationToFront(void)
-
- {
- EventRecord theEvent;
-
- /* The "Programmer's guide to MultiFinder™ says make an event call several times.
- I guess 3 calls counts as several. Also, it says call GetNextEvent but we don't
- want to lose events on the floor so we use EventAvail since it seems to work OK */
- for (short i = 1; i <= 3; ++i)
- EventAvail(everyEvent, theEvent);
- }
-
- //--------------------------------------------------------------------------------------------------
- // Must be in Main segment, and generic code, because InitToolBox calls this.
- #pragma segment Main
-
- pascal void SetRGBColor(RGBColor& RGB,
- short aRed,
- short aGreen,
- short aBlue)
-
- {
- RGB.red = aRed;
- RGB.green = aGreen;
- RGB.blue = aBlue;
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAUtilitiesRes
-
- short NumToolboxTraps(void)
- /* InitGraf is always implemented (trap 0xA86E). If the trap table is big enough, trap 0xAA6E
- will always point to either Unimplemented or some other trap, but will never be the same
- as InitGraf. Thus, you can check the size of the trap table by asking if the address of
- trap 0xA86E is the same as 0xAA6E. */
-
- {
- if (NGetTrapAddress(_InitGraf, ToolTrap) == NGetTrapAddress(0xAA6E, ToolTrap))
- return 0x200;
- else
- return 0x400;
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAUtilitiesRes
-
- pascal Boolean TrapExists(short theTrap)
-
- {
- TrapType theTrapType = GetTrapType(theTrap);
- short localTrap = theTrap; // since theTrap is a const
- if (theTrapType == ToolTrap)
- {
- localTrap = (localTrap & 0x07FF);
- if (localTrap >= NumToolboxTraps())
- localTrap = _Unimplemented;
- }
-
- return NGetTrapAddress(_Unimplemented, ToolTrap) != NGetTrapAddress(localTrap, theTrapType);
- }
-
-
-